<!DOCTYPE html>
<html>
  <head>
     
    <meta charset="UTF-8">
    <title>计算机网络2 - 测开、Java后端最常见、最核心的面试题总结</title>
    <link rel="shortcut icon" href="/static/img/icon.png">
    <link rel="icon" href="/static/img/icon.png" sizes="192x192"/>
    
<link rel="stylesheet" href="/static/kico.css">
<link rel="stylesheet" href="/static/hingle.css">

    
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

    <meta name="viewport" content="width=device-width, maximum-scale=1, initial-scale=1"/>
    <meta property="og:site_name" content="测开、Java后端最常见、最核心的面试题总结">
    <meta property="og:title" content="计算机网络2"/>
    
<meta name="generator" content="Hexo 7.3.0"></head>

  <body>
    <header>
    <div class="head-title">
        <h4>测开、Java后端最常见、最核心的面试题总结</h4>
    </div>
    <div class="head-action">
        <div class="toggle-btn"></div>
        <div class="light-btn"></div>
        <div class="search-btn"></div>
    </div>
    <form class="head-search" method="post">
        <input type="text" name="s" placeholder="搜索什么？">
    </form>
    <nav class="head-menu">
        <a href="/">首页</a>
        
    </nav>
</header>

    <main>
    <div class="wrap min">
        <section class="post-title">
            <h2>计算机网络2</h2>
            <div class="post-meta">
                <time class="date">2024.07.25</time>
            
            </div>
        </section>
        <article class="post-content">
        
            <h1><span id="18tcp-与-udp-的区别">18.TCP 与 UDP 的区别</span></h1><ol>
<li><strong>是否面向连接</strong>：UDP 在传送数据之前不需要先建立连接。而 TCP 提供面向连接的服务，在传送数据之前必须先建立连接，数据传送结束后要释放连接。</li>
<li><strong>是否是可靠传输</strong>：远地主机在收到 UDP 报文后，不需要给出任何确认，并且不保证数据不丢失，不保证是否顺序到达。TCP 提供可靠的传输服务，TCP 在传递数据之前，会有三次握手来建立连接，而且在数据传递时，有确认、窗口、重传、拥塞控制机制。通过 TCP 连接传输的数据，无差错、不丢失、不重复、并且按序到达。</li>
<li><strong>是否有状态</strong>：这个和之前的“是否可靠传输”相对应。TCP 传输是有状态的，这个有状态说的是 TCP 会去记录自己发送消息的状态比如消息是否发送了、是否被接收了等等。而 UDP 是无状态服务，简单来说就是不管发出去之后的事情了。</li>
<li><strong>传输效率</strong>：由于使用 TCP 进行传输的时候多了连接、确认、重传等机制，所以 TCP 的传输效率要比 UDP 低很多。</li>
<li><strong>传输形式</strong>：TCP 是面向字节流的，UDP 是面向报文的。</li>
<li><strong>首部开销</strong>：TCP 首部开销（20 ～ 60 字节）比 UDP 首部开销（8 字节）要大。</li>
<li><strong>是否提供广播或多播服务</strong>：TCP 只支持点对点通信，UDP 支持一对一、一对多、多对一、多对多；</li>
</ol>
<h1><span id="19什么时候选择-tcp什么时候选-udp">19.什么时候选择 TCP，什么时候选 UDP?</span></h1><ul>
<li><strong>UDP 一般用于即时通信</strong>，比如：语音、 视频、直播等等。这些场景对传输数据的准确性要求不是特别高，比如看视频即使少个一两帧，实际给人的感觉区别也不大。</li>
<li><strong>TCP 用于对传输准确性要求特别高的场景</strong>，比如文件传输、发送和接收邮件、远程登录等等。</li>
</ul>
<h1><span id="20使用-tcp-的协议有哪些使用-udp-的协议有哪些">20.使用 TCP 的协议有哪些?使用 UDP 的协议有哪些?</span></h1><p><strong>运行于 TCP 协议之上的协议</strong>：</p>
<ol>
<li><strong>HTTP 协议（HTTP&#x2F;3.0 之前）</strong>：超文本传输协议，是一种用于传输超文本和多媒体内容的协议。</li>
<li><strong>HTTPS 协议</strong>：更安全的超文本传输协议，使用 SSL&#x2F;TLS 对数据进行加密。</li>
<li><strong>FTP 协议</strong>：文件传输协议 FTP是一种用于在计算机之间传输文件的协议。FTP 是一种不安全的协议，因为它在传输过程中不会对数据进行加密。建议在传输敏感数据时使用更安全的协议，如 <strong>SFTP</strong>。</li>
<li><strong>SMTP 协议</strong>：简单邮件传输协议，是一种用于发送电子邮件的协议。</li>
<li><strong>POP3&#x2F;IMAP 协议</strong>：两者都是负责邮件接收的协议。IMAP 协议是比 POP3 更新的协议，它在功能和性能上都更加强大。IMAP 支持邮件搜索、标记、分类、归档等高级功能，而且可以在多个设备之间同步邮件状态。几乎所有现代电子邮件客户端和服务器都支持 IMAP。</li>
<li><strong>Telnet 协议</strong>：用于通过一个终端登陆到其他服务器。Telnet 协议的最大缺点之一是所有数据（包括用户名和密码）均以明文形式发送，这有潜在的安全风险。这就是为什么如今很少使用 Telnet，而是使用一种称为 SSH 的非常安全的网络传输协议的主要原因。</li>
<li><strong>SSH 协议</strong> : SSH是目前较可靠，专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH 建立在可靠的传输协议 TCP 之上。</li>
</ol>
<p><strong>运行于 UDP 协议之上的协议</strong>：</p>
<ol>
<li><strong>HTTP 协议（HTTP&#x2F;3.0 ）</strong>： HTTP&#x2F;3.0 弃用 TCP，改用基于 UDP 的 QUIC 协议 。</li>
<li><strong>DHCP 协议</strong>：动态主机配置协议，用于动态配置 IP 地址</li>
<li><strong>DNS</strong>：域名解析系统</li>
</ol>
<h1><span id="21tcp的三次握手">21.TCP的三次握手</span></h1><p>TCP（三次握手）的过程是为了建立一个可靠的连接，确保客户端和服务器都能正常通信。以下是三次握手的步骤：</p>
<ol>
<li><p><strong>第一次握手：SYN</strong></p>
<ul>
<li>客户端向服务器发送一个SYN（同步序列编号）报文段，用来表示客户端请求建立连接。该报文段包含了客户端的初始序列号。</li>
<li>此时，客户端进入 <code>SYN_SENT</code> 状态。</li>
</ul>
</li>
<li><p><strong>第二次握手：SYN-ACK</strong></p>
<ul>
<li>服务器收到SYN报文后，回应一个SYN-ACK报文段。这个报文段包含服务器的初始序列号以及对客户端的SYN报文的确认序列号，即客户端发送的序列号加1。</li>
<li>服务器此时进入 <code>SYN_RECEIVED</code> 状态。</li>
</ul>
</li>
<li><p><strong>第三次握手：ACK</strong></p>
<ul>
<li>客户端收到服务器的 SYN-ACK 报文后，向服务器发送一个ACK 报文段。这个报文段确认了服务器的序列号，即服务器的序列号加1。</li>
<li>发送完这个报文段后，客户端进入 <code>ESTABLISHED</code> 状态，表示连接已建立。</li>
<li>服务器在收到这个ACK报文段后，也进入 <code>ESTABLISHED</code> 状态。</li>
</ul>
</li>
</ol>
<p>通过这三次握手，TCP连接建立起来，双方可以开始可靠地传输数据。</p>
<h1><span id="22为什么握手是三次而不是两次或者四次">22.为什么握手是三次，而不是两次或者四次？</span></h1><ol>
<li><strong>为什么不是两次握手？</strong></li>
</ol>
<p>两次握手不能保证双方的序列号同步，并且容易导致“已失效的连接请求”问题。</p>
<ul>
<li><p><strong>序列号同步问题</strong>：</p>
<ul>
<li>在两次握手的情况下，客户端发送SYN报文后，服务器立即返回SYN+ACK，客户端收到ACK后认为连接已建立。但是，如果服务器的SYN包在网络中延迟，而客户端已经认为连接成功并发送数据，这可能会导致服务器的数据接收顺序混乱。</li>
</ul>
</li>
<li><p><strong>已失效的连接请求问题</strong>：</p>
<ul>
<li>如果客户端发送的SYN包因为网络延迟而长时间未到达服务器，而客户端在此期间因超时重新发送了一个新的SYN包。当服务器最终收到第一个（旧的）SYN包时，如果仅有两次握手，服务器可能会误认为是一个新的连接请求并建立连接，从而导致不必要的连接建立。</li>
</ul>
</li>
</ul>
<ol start="2">
<li><strong>为什么不是四次握手？</strong></li>
</ol>
<p>​	三次握手已经充分确认了双方的状态，第四次握手将会变得冗余而增加通信开销，因为没有额外的信息需要确认。</p>
<h1><span id="23第二次握手传回了-ack为什么还要传回-syn">23.第二次握手传回了 ACK，为什么还要传回 SYN？</span></h1><p>ACK用于确认客户端的SYN，确保客户端的SYN包已被成功接收。<br>而SYN用于服务器自己的连接请求，TCP连接是双向的，客户端和服务器都需要同步彼此的序列号。虽然客户端请求连接，但服务器也需要向客户端发送自己的SYN包，以便客户端确认服务器的初始序列号。</p>
<h1><span id="24三次握手过程中可以携带数据吗">24.三次握手过程中可以携带数据吗？</span></h1><p>第一次、第二次握手不可以携带数据，而第三次握手是可以携带数据的。<br>假如第一次握手可以携带数据的话，如果有人要恶意攻击服务器，那他每次都在第一次握手中的 SYN 报文中放入大量的数据，疯狂的发送 SYN 报文，这会让服务器花费大量的内存空间来缓存这些报文，这样服务器就容易被攻击了。这其实就是我们常说的SYN洪泛攻击。<br>对于第三次握手，此时客户端已经处于连接状态，他已经知道服务器的接收、发送能力是正常的了，所以可以携带数据是情理之中。</p>
<h1><span id="25tcp四次挥手">25.TCP四次挥手</span></h1><p>断开一个 TCP 连接则需要“四次挥手”，缺一不可：</p>
<ol>
<li><strong>第一次挥手</strong>：客户端发送一个 FIN 数据包到服务端，用来关闭客户端到服务端的数据传送。然后客户端进入 <strong>FIN-WAIT-1</strong> 状态。</li>
<li><strong>第二次挥手</strong>：服务端收到这个 FIN 数据包，它发送一个 ACK 数据包到客户端，这个ACK包的确认号是客户端发送的FIN包的序列号加1 。然后服务端进入 <strong>CLOSE-WAIT</strong> 状态，客户端进入 <strong>FIN-WAIT-2</strong> 状态。</li>
<li><strong>第三次挥手</strong>：服务端发送一个 FIN 数据包到客户端，请求关闭连接，然后服务端进入 <strong>LAST-ACK</strong> 状态。</li>
<li><strong>第四次挥手</strong>：客户端发送 ACK 数据包给服务端，这个ACK包的确认号是服务器发送的FIN包的序列号加1。然后客户端进入<strong>TIME-WAIT</strong>状态，服务端在收到 ACK 数据包后进入 <strong>CLOSE</strong> 状态。此时如果客户端等待 <strong>2*MSL</strong> 后依然没有收到回复，就证明服务端已正常关闭，随后客户端也可以关闭连接了。</li>
</ol>
<h1><span id="26为什么要四次挥手">26.为什么要四次挥手？</span></h1><p>TCP 是全双工通信，可以双向传输数据。任何一方都可以在数据传送结束后发出连接释放的通知，待对方确认后进入半关闭状态。当一方想要关闭连接时，发送 FIN 包表示它不再发送数据，但它仍然可能接收来自对方的数据。只有当另一方也没有数据再发送的时候，才能发出连接释放通知，对方确认后就彻底关闭 TCP 连接。</p>
<p>举个例子：A 和 B 打电话，通话即将结束后。</p>
<ol>
<li><strong>第一次挥手</strong>：A 说“我没啥要说的了”</li>
<li><strong>第二次挥手</strong>：B 回答“我知道了”，但是 B 可能还会有要说的话，A 不能要求 B 跟着自己的节奏结束通话</li>
<li><strong>第三次挥手</strong>：于是 B 可能又巴拉巴拉说了一通，最后 B 说“我说完了”</li>
<li><strong>第四次挥手</strong>：A 回答“知道了”，这样通话才算结束。</li>
</ol>
<h1><span id="27为什么不能把服务端发送的-ack-和-fin-合并起来变成三次挥手">27.为什么不能把服务端发送的 ACK 和 FIN 合并起来，变成三次挥手？</span></h1><p>因为服务端收到客户端断开连接的请求时，可能还有一些数据没有发完，这时先回复 ACK，表示接收到了断开连接的请求。等到数据发完之后再发 FIN，断开服务端到客户端的数据传送。</p>
<h1><span id="28为什么第四次挥手客户端需要等待-2msl时间后才进入-closed-状态">28.为什么第四次挥手客户端需要等待 2*MSL时间后才进入 CLOSED 状态？</span></h1><p>第四次挥手时，客户端发送给服务端的 ACK 有可能丢失，如果服务端因为某些原因而没有收到 ACK 的话，服务端就会重发 FIN，如果客户端在 2*MSL 的时间内收到了 FIN，就会重新发送 ACK 并再次等待 2MSL，防止服务端没有收到 ACK 而不断重发 FIN。</p>
<blockquote>
<p><strong>MSL(Maximum Segment Lifetime)</strong> : 报文在网络中最大的存活时间，2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSL，Client 都没有再次收到 FIN，那么 Client 推断 ACK 已经被成功接收，则结束 TCP 连接。</p>
</blockquote>

        </article>
        <section class="post-near">
            <ul>
                
                    <li>上一篇: <a href="/Redis2/">Redis2</a></li>
                
                
                    <li>下一篇: <a href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F2/">操作系统2</a></li>
                
            </ul>
        </section>
        
    
        <section class="post-author">
        
            <figure class="author-avatar">
                <img src="https://sdn.geekzu.org/avatar/d22eb460ecab37fcd7205e6a3c55c228?s=200&r=X&d=" alt="Hingle" />
            </figure>
        
            <div class="author-info">
                <h4>Hingle</h4>
                <p>请在这里设置你的作者信息</p>
            </div>
        </section>
    
    </div>
</main>

    <footer>
    <div class="buttons">
        <a class="to-top" href="#"></a>
    </div>
    <div class="wrap min">
        <section class="widget">
            <div class="row">
                <div class="col-m-4">
                    <h3 class="title-recent">最新文章：</h3>
                    <ul class="post-list"><li class="post-list-item"><a class="post-list-link" href="/%E9%A1%B9%E7%9B%AE/">项目</a></li><li class="post-list-item"><a class="post-list-link" href="/MySQL2/">MySQL2</a></li><li class="post-list-item"><a class="post-list-link" href="/Java17%E6%96%B0%E7%89%B9%E6%80%A7/">Java17新特性</a></li><li class="post-list-item"><a class="post-list-link" href="/Redis2/">Redis2</a></li><li class="post-list-item"><a class="post-list-link" href="/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C2/">计算机网络2</a></li><li class="post-list-item"><a class="post-list-link" href="/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F2/">操作系统2</a></li></ul>
                </div>
            </div>
        </section>
        <section class="sub-footer">
            <p>© 2024 <a href="/">测开、Java后端最常见、最核心的面试题总结</a>. All Rights Reserved. Theme By <a href="https://github.com/Dreamer-Paul/Hingle" target="_blank" rel="nofollow">Hingle</a>.</p>
        </section>
    </div>
</footer>


<script src="/static/kico.js"></script>
<script src="/static/hingle.js"></script>


<script>var hingle = new Paul_Hingle({"copyright":false,"night":false});</script>

  </body>
</html>
